package local.kexnichi.appengine.gcalfinance.utility;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Collections;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import com.google.api.client.auth.oauth2.AuthorizationCodeFlow;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.appengine.auth.oauth2.AppEngineCredentialStore;
import com.google.api.client.extensions.appengine.http.UrlFetchTransport;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;

public class Utility {

    public static final HttpTransport HTTP_TRANSPORT = new UrlFetchTransport();
    public static final JsonFactory JSON_FACTORY = new JacksonFactory();
    private static GoogleClientSecrets clientSecrets = null;

    public static String getRedirectUri(HttpServletRequest request)
            throws ServletException, IOException {
        GenericUrl url = new GenericUrl(request.getRequestURL().toString());
        url.setRawPath("/callback");
        return url.build();
    }

    public static AuthorizationCodeFlow initializeFlow()
            throws ServletException, IOException {
        return new GoogleAuthorizationCodeFlow.Builder(
                HTTP_TRANSPORT,
                JSON_FACTORY,
                getClientCredential(),
                Collections
                        .singleton(com.google.api.services.calendar.CalendarScopes.CALENDAR
                                + " "
                                + com.google.api.services.calendar.CalendarScopes.CALENDAR_READONLY))
                .setCredentialStore(new AppEngineCredentialStore())
                .setAccessType("offline").build();
    }

    public static com.google.api.services.calendar.Calendar loadCalendarClient()
            throws IOException, ServletException {
        String userId = UserServiceFactory.getUserService().getCurrentUser()
                .getUserId();
        Credential credential = initializeFlow().loadCredential(userId);
        return new com.google.api.services.calendar.Calendar.Builder(
                HTTP_TRANSPORT, JSON_FACTORY, credential).build();
    }

    private static GoogleClientSecrets getClientCredential() throws IOException {
        if (clientSecrets == null) {
            clientSecrets = GoogleClientSecrets.load(JSON_FACTORY,
                    Utility.class.getResourceAsStream("/client_secrets.json"));
            Preconditions
                    .checkArgument(
                            !clientSecrets.getDetails().getClientId()
                                    .startsWith("Enter ")
                                    && !clientSecrets.getDetails()
                                            .getClientSecret()
                                            .startsWith("Enter "),
                            "Download client_secrets.json file from https://code.google.com/apis/console/?api=calendar "
                                    + "into /src/main/resources/client_secrets.json");
        }
        return clientSecrets;
    }

    public static String getYYYYMMDD(Calendar cal) {
        return cal.get(Calendar.YEAR) + "-"
                + Strings.padStart("" + (cal.get(Calendar.MONTH) + 1), 2, '0')
                + "-"
                + Strings.padStart("" + cal.get(Calendar.DAY_OF_MONTH), 2, '0');
    }

    public static void createParamString(StringBuilder sb,
            String[] paramValues, String paramName)
            throws UnsupportedEncodingException {
        if (paramValues != null) {
            for (String s : paramValues) {
                sb.append(paramName);
                sb.append("=");
                sb.append(URLEncoder.encode(s, "UTF-8"));
                sb.append("&");
            }
        }
    }

    /**
     * HTMLエンコード
     * 
     * @param str
     * @return HTMLエンコードされた文字列
     */
    public static String htmlEncode(String str) {
        return str.replaceAll("'", "&#39;").replaceAll("\"", "&quot;")
                .replaceAll("&", "&amp;").replaceAll("<", "&lt;")
                .replaceAll(">", "&gt;");
    }

    /**
     * HTMLエンコード
     * 
     * @param str
     * @return HTMLエンコードされた文字列
     */
    public static StringBuilder htmlEncode(StringBuilder sb) {
        return sb.replace(0, sb.length(), htmlEncode(sb.toString()));
    }

    private Utility() {
    }
}
